#include "dominion.h"
#include "dominion_helpers.h"
#include "rngs.h"
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "testHelper.c"

#define MAX_CARDS 16
#define MIN_PLAYERS 2
#define MAX_PLAYERS 4
#define MODULUS 2147483647

int checkScore(int player, struct gameState *testState) {
  int i, testScore, ControlScore;
  struct gameState controlState;

  memcpy (&controlState, testState, sizeof(struct gameState));

  testScore = scoreFor(player, testState);

  /* SIMULATE THE FUNCTION EFFECT */
  ControlScore = 0;
  player = controlState.whoseTurn;
  for(i = 0; i < controlState.handCount[player]; i++){ //for each card in the player's hand
    if (controlState.hand[player][i] == curse) { ControlScore = ControlScore - 1; };
    if (controlState.hand[player][i] == estate) { ControlScore = ControlScore + 1; };
    if (controlState.hand[player][i] == duchy) { ControlScore = ControlScore + 3; };
    if (controlState.hand[player][i] == province) { ControlScore = ControlScore + 6; };
    if (controlState.hand[player][i] == great_hall) { ControlScore = ControlScore + 1; };
    if (controlState.hand[player][i] == gardens) { ControlScore = ControlScore + ( fullDeckCount(player, 0, &controlState) / 10 ); };
  }
  for(i = 0; i < controlState.discardCount[player]; i++){ //for each card in the player's discard pile
    if (controlState.discard[player][i] == curse) { ControlScore = ControlScore - 1; };
    if (controlState.discard[player][i] == estate) { ControlScore = ControlScore + 1; };
    if (controlState.discard[player][i] == duchy) { ControlScore = ControlScore + 3; };
    if (controlState.discard[player][i] == province) { ControlScore = ControlScore + 6; };
    if (controlState.discard[player][i] == great_hall) { ControlScore = ControlScore + 1; };
    if (controlState.discard[player][i] == gardens) { ControlScore = ControlScore + ( fullDeckCount(player, 0, &controlState) / 10 ); };
  }    
  for(i = 0; i < controlState.deckCount[player]; i++){ //for each card in the player's discard pile
    if (controlState.deck[player][i] == curse) { ControlScore = ControlScore - 1; };
    if (controlState.deck[player][i] == estate) { ControlScore = ControlScore + 1; };
    if (controlState.deck[player][i] == duchy) { ControlScore = ControlScore + 3; };
    if (controlState.deck[player][i] == province) { ControlScore = ControlScore + 6; };
    if (controlState.deck[player][i] == great_hall) { ControlScore = ControlScore + 1; };
    if (controlState.deck[player][i] == gardens) { ControlScore = ControlScore + ( fullDeckCount(player, 0, &controlState) / 10 ); };
  }    
  
  /* test to see if both the states are the same */
  if(ControlScore == testScore){
    return 0;
  }
  else{
    printf("***Failed Test***\nTest Score: %d\nControl Score: %d\n\n", testScore, ControlScore);
    return 1;
  }
}

int main () {
  int i, j, n, numPlayers, seed, success, failure, playerUnderTest;
  int k[10] = {adventurer, council_room, feast, gardens, mine,
	       remodel, smithy, village, baron, great_hall};
  struct gameState G;
  
  printf ("\n***TESTING SCORE FOR***\n");

  PutSeed(floor(Random() * MODULUS));
  success = 0;
  failure = 0;

  for (n = 0; n < 2000; n++) {
    /* Fill the Game State with garbage */
    for (i = 0; i < sizeof(struct gameState); i++) {
      ((char*)&G)[i] = floor(Random() * 256);
    }
    //initialize new game
    numPlayers = floor(Random() * PLAYER_RANGE) + 2;
    seed = floor(Random() * 1000);
    initializeGame(numPlayers, k, seed, &G);
    for (i = 0; i < numPlayers; i++){
      /* give each player a deck of random size */
      G.deckCount[i] = floor(Random() * MAX_DECK) + 5; //enough cards to draw from
      /* give each player a discard deck of random size */
      G.discardCount[i] = floor(Random() * MAX_DECK);
      /* give each player a hand of random size */
      G.handCount[i] = floor(Random() * MAX_HAND);
      /* fill each players' hand with random cards */
      for (j = 0; j < G.handCount[i]; j++){
	G.hand[i][j] = (Random() * (treasure_map + 1));
      }
    }
    playerUnderTest = floor(Random() * numPlayers); //set a player to be tested
    G.whoseTurn = playerUnderTest; //set them to current player in gameState

    if(checkScore(playerUnderTest, &G) == 0){ //run test
      success++;
    }
    else{
      failure++;
    }
  }

  printf ("\n***TESTS COMPLETE***\n***SUMMARY\n***Successful Tests: %d\n***Failed Tests: %d\n\n", success, failure);  
  return 0;
}


